using System;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Windows.Forms;

namespace UselessExplorer.UI
{
    public class DirectoryTree : TreeView
    {
        public delegate void DirectorySelectedDelegate(object sender, DirectorySelectedEventArgs e);
        public event DirectorySelectedDelegate DirectorySelected;
        ClsGlobal cg = ClsGlobal.Instance;

        private String drive;
        public String Drive
        {
            get
            {
                return drive;
            }
            set
            {
                drive = value;
                RefreshDisplay();
            }
        }

        // This is public so a Refresh can be triggered manually.
        public void RefreshDisplay()
        {
            // Erase the existing tree.
            this.Nodes.Clear();

            // Set the first node.
            TreeNode rootNode = new TreeNode(drive + @"\");
            this.Nodes.Add(rootNode);

            // Fill the first level and expand it.
            Fill(rootNode);
            this.Nodes[0].Expand();
        }

        private void Fill(TreeNode dirNode)
        {
            DirectoryInfo dir = new DirectoryInfo(dirNode.FullPath);

            // An exception could be thrown in this code if you don't
            // have sufficient security permissions for a file or directory.
            // You can catch and then ignore this exception.
            
            try
            {
                foreach (DirectoryInfo dirItem in dir.GetDirectories())
                {
                    // Add node for the directory.
                    TreeNode newNode = new TreeNode(dirItem.Name);
                    newNode.ImageIndex = 1;
                    dirNode.Nodes.Add(newNode);
                    newNode.Nodes.Add("*");
                }
            }
            catch (Exception ex)
            {
                dirNode.Nodes.Add(ex.Message);
                cg.WriteLogs(Logger.LogsCategory.Exception, ex);
            }
        }

        private bool CheckReadAccess(WindowsIdentity user, DirectoryInfo directory)
        {
            // Get the collection of authorization rules that apply to
            AuthorizationRuleCollection acl = directory.GetAccessControl().GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));

            // These are set to true if either the allow read or deny read access rights are set
            bool allowRead = false;
            bool denyRead = false;

            for (int x = 0; x < acl.Count; x++)
            {
                FileSystemAccessRule currentRule = (FileSystemAccessRule)acl[x];
                // If the current rule applies to the current user
                if (user.User.Equals(currentRule.IdentityReference))
                {
                    if
                    (currentRule.AccessControlType.Equals(AccessControlType.Deny))
                    {
                        if ((currentRule.FileSystemRights &
                        FileSystemRights.Read) == FileSystemRights.Read)
                        {
                            denyRead = true;
                        }
                    }
                    else if
                    (currentRule.AccessControlType.Equals(AccessControlType.Allow))
                    {
                        if ((currentRule.FileSystemRights &
                        FileSystemRights.Read) == FileSystemRights.Read)
                        {
                            allowRead = true;
                        }
                    }
                }
            }

            if (allowRead & !denyRead)
                return true;
            else
                return false;


        }



        protected override void OnBeforeExpand(TreeViewCancelEventArgs e)
        {
            base.OnBeforeExpand(e);

            // If a dummy node is found, remove it and read the real directory list.
            if (e.Node.Nodes[0].Text == "*")
            {
                e.Node.Nodes.Clear();
                Fill(e.Node);
            }
        }

        protected override void OnAfterSelect(TreeViewEventArgs e)
        {
            base.OnAfterSelect(e);

            // Raise the DirectorySelected event.
            if (DirectorySelected != null)
            {
                DirectorySelected(this,
                    new DirectorySelectedEventArgs(e.Node.FullPath));
            }
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // DirectoryTree
            // 
            this.LineColor = System.Drawing.Color.Black;
            this.ResumeLayout(false);

        }

    }

    public class DirectorySelectedEventArgs : EventArgs
    {
        public string DirectoryName;

        public DirectorySelectedEventArgs(string directoryName)
        {
            this.DirectoryName = directoryName;
        }
    }

}
